# coding:utf-8
from dataclasses import dataclass
import re
import os
import sys
import json
from tkinter.tix import ComboBox
from typing import Callable, Dict, List, Optional
from PyQt6.QtCore import Qt, QUrl
from PyQt6.QtWidgets import (
    QWidget,
    QHBoxLayout,
    QVBoxLayout,
    QFrame,
    QFormLayout,
    QLabel,
    QSlider,
    QLineEdit,
    QComboBox,
    QSpinBox,
    QPushButton,
    QTableWidget,
    QTableWidgetItem,
    QHeaderView,
    QSpacerItem,
    QSizePolicy,
    QCompleter,
    QTextEdit,
)
from qfluentwidgets import (
    IconWidget,
    FluentIcon,
    StrongBodyLabel,
    CardWidget,
    MessageBoxBase,
    SearchLineEdit,
    PushButton,
    LineEdit,
    Slider,
    SubtitleLabel,
)
from qframelesswindow.webengine import FramelessWebEngineView

from common.utils.JsonReplace import JsonPlaceholderReplacer
from views.common.style_sheet import StyleSheet


from .base_gallery_view import GalleryInterface
from .common.translator import Translator
from .base_gallery_view import GalleryInterface


@dataclass
class FormItemDto:

    # 表单描述
    form_desc: str

    # 表单主键
    form_key: str

    # 表单值
    form_value: str = ""

    # 表单值类型
    form_value_type: str = "text"

    # 表单最大值
    form_max: int = None

    # 表单最小值
    form_min: int = None

    # 表单关联表
    form_table: str = ""


@dataclass
class TableDataDto:

    # 表格头
    table_header: List[str]

    # 表格明细
    table_data: List[List[str]]

    # 操作按钮 : value 是回调函数 ，接收一个字符串 ， 返回一个 message
    table_item_fun: List[Dict[str, Callable[[str], str]]]


@dataclass
class ComponentConfig:
    """用于存储每个组件的配置"""

    component_type: str  # 组件类型，如 "QLineEdit", "PushButton", 等
    callback: Callable  # 回调函数
    kwargs: Optional[dict] = None  # 额外的配置信息，如按钮名称、宽度等

    def __post_init__(self):
        """确保 kwargs 总是一个字典，即使没有传递 kwargs 参数"""
        if self.kwargs is None:
            self.kwargs = {}


class BasePageTemplateView(GalleryInterface):
    """Scroll interface"""

    def __init__(self, objectName, parent=None):
        t = Translator()
        super().__init__(
            title=t.scroll, subtitle="qfluentwidgets.components.widgets", parent=parent
        )
        self.setObjectName(objectName)
        self.loaded = False
        self.searchKey = ""
        self.childTempalte = {}

    def getTopView(self):
        return QWidget

    # 添加外部组件
    def addOutLayout(self, layout):
        self.vBoxLayout.addLayout(layout)

    # 添加表单组件
    def addFromTemplate(
        self, form_items: List[FormItemDto], title, callback, stretch=0, layout=None
    ):
        form = MainFormTemplate(form_items, callback)
        card = MainCardTemplate(title, form, stretch, self.view)

        target_layout = layout if layout is not None else self.vBoxLayout
        target_layout.addWidget(card, stretch, Qt.AlignmentFlag.AlignTop)

        self.childTempalte[title] = form
        return target_layout

    # 添加报表组件
    def addEchatTemplate(
        self,
        title,
        chatName,
        dataFun: Callable[[str, Dict[str, str]], str],
        datParamFun: Callable[[], Dict[str, str]],
        stretch=0,
        layout=None,
    ):
        chat = MainEchatTemplate(chatName, dataFun, datParamFun)
        card = MainCardTemplate(title, chat, stretch, self.view)

        target_layout = layout if layout is not None else self.vBoxLayout
        target_layout.addWidget(card, stretch, Qt.AlignmentFlag.AlignTop)

        self.childTempalte[title] = chat
        return target_layout

    # 添加表格组件
    def addTableTemplate(
        self,
        title,
        dataFun: Callable[[Dict[str, str]], TableDataDto],
        datParamFun: Callable[[], Dict[str, str]],
        stretch=0,
        layout=None,
    ):
        table = MainTableTemplate(dataFun, datParamFun)
        card = MainCardTemplate(title, table, stretch, self.view)

        target_layout = layout if layout is not None else self.vBoxLayout
        target_layout.addWidget(card, stretch, Qt.AlignmentFlag.AlignTop)

        self.childTempalte[title] = table
        return target_layout

    # 添加Key-value报表组件
    def addKeyValueFormTemplate(
        self,
        title,
        dataFun: Callable[[str, Dict[str, str]], Dict[str, str]],
        datParamFun: Callable[[], Dict[str, str]],
        stretch=0,
        layout=None,
    ):
        form = MainKeyValueFrom(dataFun, datParamFun)
        card = MainCardTemplate(title, form, stretch, self.view)

        target_layout = layout if layout is not None else self.vBoxLayout
        target_layout.addWidget(card, stretch, Qt.AlignmentFlag.AlignTop)

        self.childTempalte[title] = form
        return target_layout

    def addTopOperation(
        self,
        title,
        component_configs: list[ComponentConfig],  # 组件类型与回调函数的映射
        datParamFun: Callable[[], Dict[str, str]],
        stretch=0,
        layout=None,
    ):
        top = TopSearchTemplate(component_configs, datParamFun)
        target_layout = layout if layout is not None else self.vBoxLayout
        target_layout.addWidget(top, stretch, Qt.AlignmentFlag.AlignTop)
        return target_layout

    def showEvent(self, event):
        super().showEvent(event)
        if not self.loaded:
            self.loaded = True
            self.doInitAndUpdate()
            StyleSheet.GALLERY_INTERFACE.apply(self)

    # 刷新单个 Template 的数据
    def refreshDataForTemplate(self, title: str):
        """刷新指定标题的 Template 数据"""
        template = self.childTempalte.get(title)
        if template:
            # 检查是否具有 refreshData 方法
            if hasattr(template, "refreshData") and callable(
                getattr(template, "refreshData")
            ):
                template.refreshData()
            else:
                AntLogger.info(f"模板 '{title}' 没有实现 refreshData 方法")
        else:
            AntLogger.info(f"没有找到标题为 '{title}' 的 Template")

    # 刷新所有 Template 的数据
    def refreshAllData(self):
        """刷新所有 Template 的数据"""
        for title, template in self.childTempalte.items():
            # 检查是否具有 refreshData 方法
            if hasattr(template, "refreshData") and callable(
                getattr(template, "refreshData")
            ):
                template.refreshData()
            else:
                AntLogger.info(f"模板 '{title}' 没有实现 refreshData 方法")


class MainCardTemplate(CardWidget):
    """通用卡片对象"""

    def __init__(self, title, widget: QWidget, stretch=0, parent=None):
        super().__init__(parent=parent)
        self.widget = widget
        self.stretch = stretch

        self.titleLabel = StrongBodyLabel(title, self)
        self.titleLabel.setObjectName("myTitleLabel")
        self.card = QFrame(self)

        self.sourceWidget = QFrame(self.card)

        self.vBoxLayout = QVBoxLayout(self)
        self.cardLayout = QVBoxLayout(self.card)
        self.topLayout = QHBoxLayout()

        self.__initWidget()

        self.setStyleSheet(
            """
            #myTitleLabel {
                background-color: white;      /* 白色背景 */
                border-radius: 10px;         /* 圆角 */
                padding: 10px;              /* 内边距 */
                text-indent: 10px;          /* 文字缩进 */
            }
        """
        )

    def __initWidget(self):
        self.__initLayout()

        self.sourceWidget.setCursor(Qt.CursorShape.PointingHandCursor)
        self.sourceWidget.installEventFilter(self)

        self.card.setObjectName("card")
        self.sourceWidget.setObjectName("sourceWidget")

    def __initLayout(self):
        self.vBoxLayout.setSizeConstraint(QVBoxLayout.SizeConstraint.SetMinimumSize)
        self.cardLayout.setSizeConstraint(QVBoxLayout.SizeConstraint.SetMinimumSize)
        self.topLayout.setSizeConstraint(QHBoxLayout.SizeConstraint.SetMinimumSize)

        self.vBoxLayout.setSpacing(12)
        self.vBoxLayout.setContentsMargins(0, 0, 0, 0)
        self.topLayout.setContentsMargins(12, 12, 12, 12)
        self.cardLayout.setContentsMargins(0, 0, 0, 0)

        self.vBoxLayout.addWidget(self.titleLabel, 0, Qt.AlignmentFlag.AlignTop)
        self.vBoxLayout.addWidget(self.card, 0, Qt.AlignmentFlag.AlignTop)
        self.vBoxLayout.setAlignment(Qt.AlignmentFlag.AlignTop)

        self.cardLayout.setSpacing(0)
        self.cardLayout.setAlignment(Qt.AlignmentFlag.AlignTop)
        self.cardLayout.addLayout(self.topLayout, 0)
        self.cardLayout.addWidget(self.sourceWidget, 0, Qt.AlignmentFlag.AlignBottom)

        self.widget.setParent(self.card)
        self.topLayout.addWidget(self.widget)
        if self.stretch == 0:
            self.topLayout.addStretch(1)

        self.widget.show()


class MainFormTemplate(QWidget):
    def __init__(self, form_items: List[FormItemDto], callback=None):
        super().__init__()
        self.form_items = form_items
        self.callback = callback
        self.setMinimumWidth(1000)
        self.init_ui()

    def init_ui(self):
        self.viewLayout = QVBoxLayout()
        self.formLayout = QFormLayout()
        self.formLayout.setVerticalSpacing(10)
        self.fields = {}  # 存储控件的引用
        for item in self.form_items:
            label = QLabel(item.form_desc)

            if item.form_value_type == "text":
                input_field = QLineEdit(self)
                input_field.setPlaceholderText(self.tr(f"请输入 {item.form_desc}"))
                input_field.setText(item.form_value or "")
                input_field.setClearButtonEnabled(True)
            elif item.form_value_type == "int":
                input_field = QLineEdit(self)
                input_field.setPlaceholderText(self.tr(f"请输入 {item.form_desc}"))
                input_field.setText(item.form_value or "")
                input_field.setClearButtonEnabled(True)
            elif item.form_value_type == "slider":
                input_field = QSlider(Qt.Orientation.Horizontal, self)
                input_field.setRange(item.form_min or 0, item.form_max or 100)
                input_field.setValue(
                    int(item.form_value) if item.form_value.isdigit() else 0
                )
                input_field.setTickInterval(1)
                input_field.setSingleStep(1)
            elif item.form_value_type == "select":
                input_field = QComboBox(self)
                if item.form_table:
                    options = item.form_table.split(",")  # 以逗号分隔的选项
                    input_field.addItems(options)
                if item.form_value:
                    input_field.setCurrentText(item.form_value)
            else:
                input_field = QLabel(self.tr(f"不支持的类型: {item.form_value_type}"))

            input_field.setMinimumHeight(30)
            input_field.setProperty("form_name", item.form_desc)
            self.formLayout.addRow(label, input_field)
            self.fields[item.form_key] = input_field  # 根据表单主键存储引用

        # 提交按钮
        self.submit_button = QPushButton("提交")
        self.submit_button.setFixedWidth(100)
        self.submit_button.setFixedHeight(40)
        self.submit_button.clicked.connect(self.submit_form)

        self.button_layout = QHBoxLayout()
        self.button_layout.addStretch()  # 添加弹性空间，将按钮推到右边
        self.button_layout.addWidget(
            self.submit_button, alignment=Qt.AlignmentFlag.AlignRight
        )

        self.viewLayout.addLayout(self.formLayout)
        self.viewLayout.addLayout(self.button_layout)
        self.viewLayout.setContentsMargins(15, 10, 10, 10)  # 设置边距
        self.viewLayout.setSpacing(15)

        self.setLayout(self.viewLayout)
        self.setWindowTitle("Dynamic Form")

    def submit_form(self):
        form_items = []
        for key, widget in self.fields.items():
            if isinstance(widget, QLineEdit):
                form_value = widget.text()
                form_value_type = "text"
            elif isinstance(widget, QSpinBox):
                form_value = str(widget.value())  # 转换为字符串以符合 DTO 定义
                form_value_type = "int"
            elif isinstance(widget, QComboBox):
                form_value = widget.currentText()
                form_value_type = "select"
            else:
                form_value = None
                form_value_type = "unknown"

            # 根据控件构建 FormItemDto 对象
            item = FormItemDto(
                form_desc=widget.property("form_name"),
                form_key=key,
                form_value=form_value,
                form_value_type=form_value_type,
                form_max=widget.maximum() if hasattr(widget, "maximum") else None,
                form_min=widget.minimum() if hasattr(widget, "minimum") else None,
                form_table=(
                    ",".join([widget.itemText(i) for i in range(widget.count())])
                    if isinstance(widget, QComboBox)
                    else ""
                ),
            )

            form_items.append(item)

        if self.callback:
            self.callback(form_items)
        else:
            AntLogger.info("Form Data DTO List:")
            for item in form_items:
                AntLogger.infoitem)


class MainEchatTemplate(QWidget):
    """通用表格创建类"""

    def __init__(
        self,
        chatName: str,
        dataFun: Callable[[str, Dict[str, str]], str],
        datParamFun: Callable[[], Dict[str, str]],
    ):
        super().__init__()
        self.dataFun = dataFun
        self.datParamFun = datParamFun
        self.chatName = chatName
        self.setMinimumWidth(500)
        self.setMinimumHeight(500)
        self.init_ui()

    def init_ui(self):

        # 水平视图 ： Chat 默认以水平试图分为左右两个部分
        self.viewLayout = QHBoxLayout()

        # 左侧为Echat 图表
        self.chatLeftLayout = QVBoxLayout()
        self.webView = FramelessWebEngineView(self)
        self.chatLeftLayout.addWidget(self.webView)

        # 调用方法完成布局
        self.setup_layout()

        # 刷新 Echat
        self.do_load_chat()

    def setup_layout(self):
        # 将左侧和右侧布局作为小部件添加到 viewLayout
        left_widget = QWidget()
        left_widget.setLayout(self.chatLeftLayout)

        # 设置左侧最小宽度和高度
        left_widget.setMinimumWidth(300)  # 设置最小宽度为 300 像素
        left_widget.setMinimumHeight(400)  # 设置最小高度为 400 像素

        # 添加左右布局到水平布局
        self.viewLayout.addWidget(left_widget)

        # 设置 viewLayout 为当前窗口的主布局
        self.setLayout(self.viewLayout)

    def do_load_chat(self):
        current_dir = os.path.dirname(os.path.abspath(__file__)) + "\\common\\html\\"
        chatHTMLFile = self.chatName + ".html"
        self.chatPath = os.path.join(current_dir, chatHTMLFile)
        self.webView.load(QUrl.fromLocalFile(self.chatPath))
        self.webView.loadFinished.connect(self.do_load_data)

    def do_load_data(self):

        # 开始加载 JSON 进行替换
        current_dir = os.path.dirname(os.path.abspath(__file__)) + "\\common\\html\\"
        chatJSONFile = self.chatName + ".json"
        local_file_path = os.path.join(current_dir, chatJSONFile)

        json_data = ""
        with open(local_file_path, "r", encoding="utf-8") as file:
            json_data = json.load(file)

        # 调用函数方法进行解析
        chatData = self.dataFun(json_data, self.datParamFun)

        js_code = f"setData({chatData});"
        AntLogger.info(f"最终写入参数{js_code}")
        self.webView.page().runJavaScript(js_code, self.echat_callback)

    def echat_callback(self, result):
        AntLogger.info(f"JavaScript Result{result}")

    def add_right_layout(self, widget: QWidget):
        self.rightLayout.widget(widget)

    def refreshData(self):
        self.do_load_data()


class DynamicFormTemplate(MessageBoxBase):
    """动态表单生成模板"""

    def __init__(self, parent=None, form_config=None, title="表单", on_submit=None):
        """
        :param parent: 父窗口
        :param form_config: 表单配置列表，每项为字典，描述控件类型、标签、默认值等
        :param title: 表单标题
        :param on_submit: 提交回调函数，接收表单数据作为参数
        """
        super().__init__(parent)
        self.form_config = form_config or []
        self.on_submit = on_submit
        self.form_items = {}

        # 初始化界面
        self.titleLabel = SubtitleLabel(self.tr(title), self)
        self.viewLayout.addWidget(self.titleLabel)

        self.formLayout = QFormLayout()
        self.formLayout.setVerticalSpacing(10)
        self._create_form()
        self.viewLayout.addLayout(self.formLayout)

        # 提交按钮
        self.yesButton.setText(self.tr("提交"))
        self.yesButton.clicked.connect(self._submit_form)

        # 设置窗口属性
        self.widget.setMinimumWidth(360)

    def _create_form(self):
        """根据配置动态创建表单控件"""
        for config in self.form_config:
            control_type = config.get("type")
            label = config.get("label")
            key = config.get("key")
            default = config.get("default", "")
            options = config.get("options", {})

            if control_type == "line_edit":
                self._add_line_edit(label, key, default)
            elif control_type == "slider":
                self._add_slider(label, key, **options)
            elif control_type == "combo_box":
                self._add_combo_box(label, key, options.get("items", []), default)
            elif control_type == "text_edit":
                self._add_text_edit(label, key, default)
            else:
                raise ValueError(f"未知控件类型: {control_type}")

    def _add_line_edit(self, label, key, default):
        """添加文本输入框"""
        line_edit = LineEdit(self)
        line_edit.setPlaceholderText(self.tr(label))
        line_edit.setText(default)
        line_edit.setClearButtonEnabled(True)
        self.formLayout.addRow(f"{label}:", line_edit)
        self.form_items[key] = line_edit

    def _add_slider(self, label, key, min_value=0, max_value=100, initial_value=0):
        """添加滑块"""
        slider = Slider(Qt.Orientation.Horizontal)
        slider.setRange(min_value, max_value)
        slider.setValue(initial_value)

        value_label = QLabel(str(initial_value))
        value_label.setFixedWidth(30)

        slider_layout = QHBoxLayout()
        slider_layout.addWidget(slider)
        slider_layout.addWidget(value_label)
        self.formLayout.addRow(f"{label}:", slider_layout)

        self.form_items[key] = slider
        slider.valueChanged.connect(lambda v: value_label.setText(str(v)))

    def _add_combo_box(self, label, key, items, default):
        """添加下拉选择框"""
        combo_box = ComboBox(self)
        combo_box.addItems(items)
        combo_box.setCurrentText(default)
        self.formLayout.addRow(f"{label}:", combo_box)
        self.form_items[key] = combo_box

    def _add_text_edit(self, label, key, default):
        """添加多行文本输入框"""
        text_edit = QTextEdit(self)
        text_edit.setPlaceholderText(self.tr(label))
        text_edit.setText(default)
        self.formLayout.addRow(f"{label}:", text_edit)
        self.form_items[key] = text_edit

    def set_value(self, key: str, value: str | int):
        # 通用方法，设置控件值
        control_data = self.formItem.get(key)
        if not control_data:
            raise KeyError(f"控件 '{key}' 未找到！")

        control = control_data["control"]
        control_type = control_data["type"]

        if control_type == "line_edit":
            if not isinstance(value, str):
                raise ValueError(
                    f"控件 '{key}' 的值类型应为 str，但收到 {type(value).__name__}"
                )
            control.setText(value)
        elif control_type == "slider":
            if not isinstance(value, int):
                raise ValueError(
                    f"控件 '{key}' 的值类型应为 int，但收到 {type(value).__name__}"
                )
            control.setValue(value)
        else:
            raise TypeError(f"未知控件类型 '{control_type}'")

    def _submit_form(self):
        """提交表单，获取数据并触发回调"""
        form_data = {}
        for key, control in self.form_items.items():
            if isinstance(control, LineEdit):
                form_data[key] = control.text()
            elif isinstance(control, Slider):
                form_data[key] = control.value()
            elif isinstance(control, ComboBox):
                form_data[key] = control.currentText()
            elif isinstance(control, QTextEdit):
                form_data[key] = control.toPlainText()
        if self.on_submit:
            self.on_submit(form_data)


class MainTableTemplate(QWidget):
    """通用表格创建类"""

    def __init__(
        self,
        dataFun: Callable[[Dict[str, str]], TableDataDto],
        datParamFun: Callable[[], Dict[str, str]],
    ):
        super().__init__()
        self.dataFun = dataFun
        self.datParamFun = datParamFun
        self.setMinimumWidth(500)
        self.setMinimumHeight(700)

        self.tableLayout = QHBoxLayout()
        self.innerlayout = QVBoxLayout()

        left_widget = QWidget()
        left_widget.setLayout(self.innerlayout)
        self.tableLayout.addWidget(left_widget)
        self.setLayout(self.tableLayout)

        self.init_ui()

    def init_ui(self):
        """初始化表格视图"""
        # 获取表格数据
        self.load_table_data()

        # 创建 QTableWidget
        self.table_widget = QTableWidget()
        self.table_widget.setColumnCount(len(self.table_data.table_header) + 1)  # +1 为操作列
        self.table_widget.setHorizontalHeaderLabels(self.table_data.table_header + ["操作"])
        self.table_widget.setRowCount(len(self.table_data.table_data))

        # 填充表格内容
        self.populate_table()

        # 调整列宽和行高
        self.table_widget.resizeColumnsToContents()
        header = self.table_widget.horizontalHeader()
        header.setSectionResizeMode(QHeaderView.ResizeMode.Stretch)

        self.innerlayout.addWidget(self.table_widget)

    def load_table_data(self):
        """获取并加载表格数据"""
        self.table_data = self.dataFun(self.datParamFun)

    def populate_table(self):
        """填充表格内容"""
        for row_idx, row_data in enumerate(self.table_data.table_data):
            self.table_widget.setRowHeight(row_idx, 50)

            # 填充单元格数据
            for col_idx, cell_data in enumerate(row_data):
                self.table_widget.setItem(row_idx, col_idx, QTableWidgetItem(cell_data))

            # 添加操作按钮列
            self.add_action_buttons(row_idx, row_data)

    def add_action_buttons(self, row_idx: int, row_data: List[str]):
        """为指定行添加操作按钮"""
        action_buttons_layout = QHBoxLayout()

        # 遍历配置的操作按钮
        for action in self.table_data.table_item_fun:
            for action_label, action_func in action.items():
                button = QPushButton(action_label)
                button.setMinimumHeight(40)

                # 绑定按钮点击事件
                button.clicked.connect(
                    lambda _, r=row_idx, func=action_func: self.handle_action(r, row_data, func)
                )
                action_buttons_layout.addWidget(button)

        # 将按钮组放置在表格单元格中
        button_widget = QWidget()
        button_widget.setLayout(action_buttons_layout)
        self.table_widget.setCellWidget(row_idx, len(row_data), button_widget)

    def handle_action(self, row_idx: int, row_data: List[str], func: Callable[[str], str]):
        """处理操作按钮点击事件"""
        try:
            row_data_str = ", ".join(row_data)  # 将行数据拼接成字符串
            result_message = func(row_data_str)  # 调用操作函数

            AntLogger.info(f"Action result for row {row_idx}: {result_message}")
        except Exception as e:
            AntLogger.info(f"Error handling action for row {row_idx}: {e}")

    def refreshData(self):
        """刷新表格数据"""
        self.load_table_data()  # 重新加载数据

        # 清空现有的表格内容
        self.table_widget.clearContents()
        self.table_widget.setRowCount(len(self.table_data.table_data))  

        # 重新填充表格内容
        self.populate_table()

        # 调整列宽和行高
        self.table_widget.resizeColumnsToContents()
        header = self.table_widget.horizontalHeader()
        header.setSectionResizeMode(QHeaderView.ResizeMode.Stretch)

        AntLogger.info("Data refreshed successfully.")



class MainKeyValueFrom(QWidget):
    """键值对表单"""

    def __init__(
        self,
        dataFun: Callable[[Dict[str, str]], Dict[str, str]],
        datParamFun: Callable[[], Dict[str, str]],
    ):
        super().__init__()
        self.dataFun = dataFun
        self.datParamFun = datParamFun
        self.setMinimumWidth(500)
        self.setMinimumHeight(500)

        # 水平视图 ： Chat 默认以水平试图分为左右两个部分
        self.tableLayout = QHBoxLayout()
        self.setLayout(self.tableLayout)
        self.init_ui()

    def init_ui(self):
        self.table_data = self.dataFun(self.datParamFun)

        self.form_layout = QFormLayout()

        # 动态添加 Key-Value 到表单
        for key, value in self.table_data.items():
            # Key 显示为 QLabel
            key_label = QLabel(key)
            # Value 使用 QLineEdit，可以编辑
            value_field = QLineEdit(str(value))
            self.form_layout.addRow(key_label, value_field)
        self.tableLayout.addLayout(self.form_layout)

    def refreshData(self):
        """刷新数据，重新加载表单"""
        # 清空当前表单布局
        for i in reversed(range(self.form_layout.count())):
            widget = self.form_layout.itemAt(i).widget()
            if widget is not None:
                widget.deleteLater()

        # 获取最新的数据
        table_data = self.dataFun(self.datParamFun())

        # 动态添加新的 Key-Value 到表单
        for key, value in table_data.items():
            key_label = QLabel(key)
            value_field = QLineEdit(str(value))
            self.form_layout.addRow(key_label, value_field)


class TopSearchTemplate(QWidget):
    """顶部搜索框，动态加载组件并绑定回调函数"""

    def __init__(
        self,
        component_configs: list[ComponentConfig],  # 传入的组件配置列表
        datParamFun: Callable[[], Dict[str, str]],
    ):
        super().__init__()

        self.datParamFun = datParamFun
        self.setMaximumHeight(50)
        self.setMinimumHeight(50)

        # 布局
        self.hBoxLayout = QHBoxLayout()
        self.hBoxLayout.setSpacing(10)
        self.hBoxLayout.setContentsMargins(10, 10, 10, 10)
        self.hBoxLayout.setAlignment(Qt.AlignmentFlag.AlignLeft)

        # 动态加载组件
        self.__initWidgets(component_configs)

        self.setLayout(self.hBoxLayout)

    def __initWidgets(self, component_configs: list[ComponentConfig]):
        """根据传入的组件配置动态加载组件"""

        for config in component_configs:
            if config.component_type == "QLineEdit":
                # 创建 QLineEdit 并绑定 QCompleter
                searchLineEdit = TopTemplateSearchLineEdit(self)
                param = self.datParamFun()
                completer = QCompleter(param, searchLineEdit)
                completer.setCaseSensitivity(Qt.CaseSensitivity.CaseInsensitive)
                completer.setMaxVisibleItems(10)
                searchLineEdit.setCompleter(completer)
                searchLineEdit.clearSignal.connect(lambda text: config.callback(""))
                searchLineEdit.searchSignal.connect(lambda text: config.callback(text))
                searchLineEdit.setFixedHeight(30)
                self.hBoxLayout.addWidget(searchLineEdit)

            elif config.component_type == "PushButton":
                # 创建 QPushButton 并绑定回调函数
                button = QPushButton(config.kwargs.get("name", ""))
                button.setFixedWidth(config.kwargs.get("width", 120))
                button.clicked.connect(config.callback)
                button.setFixedHeight(30)
                self.hBoxLayout.addWidget(button)

            elif config.component_type == "Spacer":
                # 创建 Spacer（可选）
                spacer = QSpacerItem(20, 10, QSizePolicy.Fixed, QSizePolicy.Minimum)
                self.hBoxLayout.addItem(spacer)

        self.hBoxLayout.addStretch()


class TopTemplateSearchLineEdit(SearchLineEdit):
    """Search line edit"""

    def __init__(self, parent=None):
        super().__init__(parent)
        self.setPlaceholderText(self.tr("通过股票代码/名称查询"))
        self.setFixedWidth(304)
